package edu.hit.irlab.coref;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;

import nlpeap.ml.OfflineClassifier;
import nlpeap.ml.maxent.ClassifierBinary;
import nlpeap.ml.maxent.ClassifierSinkBinary;
import nlpeap.ml.svm.SVMLightClassifier;
import nlpeap.ml.weka.WEKAInstanceClassifier;
import nlpeap.model.eval.PRScores;
import nlpeap.toolrepository.LoadException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;

import edu.hit.irlab.coref.evaluation.Evaluation;
import edu.hit.irlab.coref.mentionfinder.DefaultCorpus_Mentionfinder;
import edu.hit.irlab.coref.mentionfinder.MentionFinder;
import edu.hit.irlab.coref.musicdomain.mentionfinder.CorpusMentionFinder;
import edu.hit.irlab.coref.postprocess.Postprocessor;
import edu.hit.irlab.coref.resolve.BinaryClassifyResolver;
import edu.hit.irlab.coref.resolve.Resolver;
import edu.hit.irlab.coref.resolve.algorithm.BestFirst;
import edu.hit.irlab.coref.resolve.algorithm.CloseFirst;
import edu.hit.irlab.coref.resolve.algorithm.ResolveAlgorithm;

/**
 * Evaluate the <i>Coreference Resolution System's</i> performance
 * @author chuter
 *
 */
public class CREvalModel {
	public static Log _log = LogFactory.getLog(CREvalModel.class.getName());
	private final Evaluation _eval;
	private static final CRConfigProperties _cprop = CRConfigProperties.getInstance();
	private static String _testCorpusPath = _cprop.getTestCorpusPath();
	
	public CREvalModel(
			MentionFinder<Document> corpusMentionFinder,
			ResolveAlgorithm resolveAlgorithm
		) {
		Postprocessor postProc = _cprop.getPostPrecessor();
		_eval = new Evaluation(corpusMentionFinder, resolveAlgorithm, postProc);		
	}
	
	public void evalCRSysPerformance() throws IOException {
		PRScores scores = _eval.evaluateCR(_testCorpusPath);
		System.out.println(scores);
	}
	
	public void evaluatMentionRecog(MentionFinder<nlpeap.tms.Document> mentionFinder) {
		try {
			_eval.evaluatMenRecog(_testCorpusPath, mentionFinder);
		} catch (IOException e) {
			_log.fatal(String.format("load file error: ", e));
			e.printStackTrace();
		}
	}
	
	public static OfflineClassifier getClassifier() {
		OfflineClassifier oc = null;
		try {
			if (_cprop.getClassifierType().equalsIgnoreCase(OfflineClassifier.WEKA)) {
				oc = new WEKAInstanceClassifier(_cprop.getModelName());
			} else if (_cprop.getClassifierType().equalsIgnoreCase(OfflineClassifier.SVM)) {
				oc = new SVMLightClassifier(
						new File(_cprop.getModelDir(), _cprop.getModelName()+".svmltk"),
		                new File(_cprop.getModelDir(), _cprop.getModelName()+".alphabet"));
			} else if (_cprop.getClassifierType().equalsIgnoreCase(OfflineClassifier.Maxent)) {
				oc = new ClassifierBinary(new File(_cprop.getModelDir(), _cprop.getModelName()).getAbsolutePath(),
						ClassifierSinkBinary.comboFromString(_cprop.getClassifierOption()));
			}
		} catch (IOException e) {
			_log.fatal(e.toString());
		} catch (ClassNotFoundException e) {
			_log.fatal(e.toString());
		}
		
		return oc;
	}
	
	public static void main(String[] argv) 
		throws LoadException, ClassNotFoundException, 
		InstantiationException, IllegalAccessException, IOException {
		
//		PrintStream out = new PrintStream(new FileOutputStream(new File("."+File.separator+"CREvalModel.log")));
//		System.setOut(out);
//		System.setErr(out);
		
		MentionFinder<Document> corpusMentionFinder = new CorpusMentionFinder();
//		MentionFinder<Document> corpusMentionFinder = new DefaultCorpus_Mentionfinder();
		ArrayList<PairFeatureExtractor> fes = CRConfigProperties.getInstance().getPairFEs();
		
		OfflineClassifier model = getClassifier();
		Resolver[] resolvers = new Resolver[]{
				new BinaryClassifyResolver(fes, model)
			};
		ResolveAlgorithm resolveAlgorithm = new CloseFirst(resolvers);
		
		CREvalModel evl = new CREvalModel(corpusMentionFinder, resolveAlgorithm);
		evl.evalCRSysPerformance();
	}
	
}

